package com.xeonwell.JerseyDemo.controller;


import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.xeonwell.JerseyDemo.dao.PodcastDao;
import com.xeonwell.JerseyDemo.model.Podcast;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by xeonwell on 2017-04-26.
 */
@Path("/podcasts")
public class PodcastsController {
    @Autowired
    private PodcastDao podcastDao;

    /************************************ CREATE ************************************/

    /**
     * Adds a new resource (podcast) from the given json format (at least title and feed elements are required
     * at the DB level)
     *
     * @param podcast
     * @return
     */
    @POST
    @Consumes({MediaType.APPLICATION_JSON})
    @Produces({MediaType.TEXT_HTML})
    @Transactional
    public Response createPodcast(Podcast podcast) {
        podcastDao.createPodcast(podcast);

        return Response.status(201).entity("A new podcast/resource has been created").build();
    }

    /**
     * Adds a new resource (podcast) from "form" (at least title and feed elements are required
     * at the DB level)
     *
     * @param title
     * @param linkOnPodcastpedia
     * @param feed
     * @param description
     * @return
     */
    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @Produces({MediaType.TEXT_HTML})
    @Transactional
    public Response createPodcastFromForm(
            @FormParam("title") String title,
            @FormParam("linkOnPodcastpedia") String linkOnPodcastpedia,
            @FormParam("feed") String feed,
            @FormParam("description") String description
    ) {
        Podcast podcast = new Podcast(title, linkOnPodcastpedia, feed, description);
        podcastDao.createPodcast(podcast);

        return Response.status(201).entity("A new podcast/resource has been created").build();
    }

    /**
     * A list of resources (here podcasts) provided in json format will be added
     * to the database.
     *
     * @param podcasts
     * @return
     */
    @POST @Path("list")
    @Consumes({MediaType.APPLICATION_JSON})
    @Transactional
    public Response createPodcasts(List<Podcast> podcasts) {
        for(Podcast podcast : podcasts){
            podcastDao.createPodcast(podcast);
        }

        return Response.status(204).build();
    }

    /************************************ READ ************************************/
    /**
     * Returns all resources (podcasts) from the database
     * @return
     */
    @GET
    @Produces({MediaType.APPLICATION_JSON})
    public List<Podcast> getPodcasts() {
        return podcastDao.getPodcasts();
    }

    @GET @Path("{id}")
    @Produces({MediaType.APPLICATION_JSON})
    public Response findById(@PathParam("id") Long id) {
        Podcast podcastById = podcastDao.getPodcastById(id);
        if(podcastById != null) {
            return Response.status(200).entity(podcastById).build();
        } else {
            return Response.status(404).entity("The podcast with the id " + id + " does not exist").build();
        }
    }


    /************************************ UPDATE ************************************/
    /**
     * Updates the attributes of the podcast received via JSON for the given @param id
     *
     * If the podcast does not exist yet in the database (verified by <strong>id</strong>) then
     * the application will try to create a new podcast resource in the db
     *
     * @param id
     * @param podcast
     * @return
     */
    @PUT @Path("{id}")
    @Consumes({MediaType.APPLICATION_JSON})
    @Produces({MediaType.TEXT_HTML})
    @Transactional
    public Response updatePodcastById(@PathParam("id") Long id, Podcast podcast) {
        if(podcast.getId() == null) podcast.setId(id);
        String message;
        int status;
        if(podcastWasUpdated(podcast)){
            status = 200; //OK
            message = "Podcast has been updated";
        } else if(podcastCanBeCreated(podcast)){
            podcastDao.createPodcast(podcast);
            status = 201; //Created
            message = "The podcast you provided has been added to the database";
        } else {
            status = 406; //Not acceptable
            message = "The information you provided is not sufficient to perform either an UPDATE or "
                    + " an INSERTION of the new podcast resource <br/>"
                    + " If you want to UPDATE please make sure you provide an existent <strong>id</strong> <br/>"
                    + " If you want to insert a new podcast please provide at least a <strong>title</strong> and the <strong>feed</strong> for the podcast resource";
        }

        return Response.status(status).entity(message).build();
    }

    private boolean podcastWasUpdated(Podcast podcast) {
        return podcastDao.updatePodcast(podcast) == 1;
    }

    private boolean podcastCanBeCreated(Podcast podcast) {
        return podcast.getFeed() != null && podcast.getTitle()!=null;
    }

    /************************************ DELETE ************************************/
    @DELETE @Path("{id}")
    @Produces({MediaType.TEXT_HTML})
    @Transactional
    public Response deletePodcastById(@PathParam("id") Long id) {
        if(podcastDao.deletePodcastById(id) == 1){
            return Response.status(204).build();
        } else {
            return Response.status(404).entity("Podcast with the id " + id + " is not present in the database").build();
        }
    }

    @DELETE
    @Produces({MediaType.TEXT_HTML})
    @Transactional
    public Response deletePodcasts() {
        podcastDao.deletePodcasts();
        return Response.status(200).entity("All podcasts have been successfully removed").build();
    }

    public void setPodcastDao(PodcastDao podcastDao) {
        this.podcastDao = podcastDao;
    }


}
